﻿using Codemonk.Common.Logging;
using System;
using System.Collections.Generic;
using System.IO;

namespace Codemonk.CloudBox.Adapters.Logging
{
    public sealed class Log4NetLog : Log, ILog
    {
        private readonly log4net.ILog log;
        private Dictionary<LogLevel, Action<object>> writeObjects;
        private Dictionary<LogLevel, Action<object, Exception>> writeObjectWithExceptions;
        private Dictionary<LogLevel, Action<string, object>> writeObjectWithFormats;
        private Dictionary<LogLevel, Action<IFormatProvider, string, object[]>> writeObjectWithFormatProviders;
        public Log4NetLog(log4net.ILog log)
        {
            this.log = log;
            writeObjects = new Dictionary<LogLevel, Action<object>>
            {
                  {LogLevel.Info,log.Info},
                  {LogLevel.Debug,log.Debug},
                  {LogLevel.Waring,log.Warn},
                  {LogLevel.Error,log.Error},
                  {LogLevel.Fatal,log.Fatal}
            };
            writeObjectWithExceptions = new Dictionary<LogLevel, Action<object, Exception>>
            {
                 {LogLevel.Info,log.Info},
                 {LogLevel.Debug,log.Debug},
                 {LogLevel.Waring,log.Warn},
                 {LogLevel.Error,log.Error},
                 {LogLevel.Fatal,log.Fatal}
            };
            writeObjectWithFormats = new Dictionary<LogLevel, Action<string, object>>
            {
                 {LogLevel.Info,log.InfoFormat},
                 {LogLevel.Debug,log.DebugFormat},
                 {LogLevel.Waring,log.WarnFormat},
                 {LogLevel.Error,log.ErrorFormat},
                 {LogLevel.Fatal,log.FatalFormat}
            };
            writeObjectWithFormatProviders = new Dictionary<LogLevel, Action<IFormatProvider, string, object[]>>
            {
                 {LogLevel.Info,log.InfoFormat},
                 {LogLevel.Debug,log.DebugFormat},
                 {LogLevel.Waring,log.WarnFormat},
                 {LogLevel.Error,log.ErrorFormat},
                 {LogLevel.Fatal,log.FatalFormat}
            };
        }

        public override void Record(LogLevel level, object message)
        {
            writeObjects[level](message);
        }

        public override void Record(LogLevel level, object message, Exception exception)
        {
            writeObjectWithExceptions[level](message, exception);
        }

        public override void Record(LogLevel level, object message, string format)
        {
            writeObjectWithFormats[level](format, message);
        }

        public override void Record(LogLevel level, object message, string format, IFormatProvider provider)
        {
            writeObjectWithFormatProviders[level](provider, format, new[] { message });
        }
    }
    public sealed class Log4NetLogFactory : ILogFactory
    {
        static Log4NetLogFactory()
        {
            log4net.Config.XmlConfigurator.Configure(new FileInfo("./config/log4net.config"));
        }
        public ILog Get(string name = null)
        {
            return new Log4NetLog(log4net.LogManager.GetLogger(string.IsNullOrWhiteSpace(name)?"default":name));
        }
    }
}
